package cleanstarxchange.server;

import java.util.ArrayList;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User implements Comparable<User>
{
	// Primary Key
	// ID taken from Facebook
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long uid;
    // Field will be stored in datastore
    // First name of user
    @Persistent
    private String firstName;
    // Field will be stored in datastore
    // Last name of user
    @Persistent
    private String lastName;
    // Field will be stored in datastore
    // Whether or not user is using app
	@Persistent 
	private boolean is_app_user;
	// Field will be stored in datastore
	// Balance of user
	@Persistent 
	private double balance;
	// Field will be stored in datastore
	// Total value of user's assets ( balance + stocks )
	@Persistent 
	private double assetValue;
	// Field will be stored in datastore
	// List of the user's asset values in the past, only store previous 50 values
	@Persistent 
	private ArrayList<Double> prevAssetValues  = new ArrayList<Double>();
	// Field will be stored in datastore
	// Previous asset value
	@Persistent 
	private double prevAssetValue;
	// Field will be stored in datastore
	// Temporary asset value
	@Persistent 
	private double tmp1;
	// Field will be stored in datastore
	// Temporary asset value
	@Persistent 
	private double tmp2;
	// Field will be stored in datastore
	// Temporary asset value
	@Persistent 
	private double tmp3;
	// Field will be stored in datastore
	// Temporary asset value
	@Persistent 
	private double tmp4;
	// Field will be stored in datastore
	// Temporary asset value
	@Persistent 
	private double tmp5;
	// Field will be stored in datastore
	// Highest asset value user has ever obtained
	@Persistent 
	private double maxAssetValue;
	DataStore ds;
	
	/**
	 * Constructor for User class
	 * @param uid - user ID from Facebook
	 * @param firstName - first name from Facebook
	 * @param lastName - last name from Facebook
	 * @param is_app_user - whether or not user is using the app
	 * @param balance - starting balance
	 */
	public User( int uid, String firstName, String lastName, boolean is_app_user, Double balance )
	{
		this.uid = new Long(uid);
		this.firstName = firstName;
		this.lastName = lastName;
		this.is_app_user = true;
		this.balance = balance;
		this.prevAssetValue = balance;
		this.assetValue = balance;
		this.tmp1 = balance;
		this.tmp2 = balance;
		this.tmp3 = balance;
		this.tmp4 = balance;
		this.tmp5 = balance;
		this.maxAssetValue = balance;
		for ( int i = 0; i < 5; i++ )
			prevAssetValues.add( balance );
	}
	
	/**
	 * Return the Facebook user ID of user
	 * @return - user ID
	 */
	public Long getUserID()
	{
		return uid;
	}
	
	/**
	 * Return the first name of the user
	 * @return - first name
	 */
	public String getFirstName()
	{
		return firstName;
	}
	
	/**
	 * Return the last name of the user
	 * @return - last name
	 */
	public String getLastName()
	{
		return lastName;
	}
	
	/**
	 * Return boolean value for whether or not user is using this app
	 * @return - true if user uses app, false otherwise
	 */
	public boolean isAppUser()
	{
		return is_app_user;
	}
	
	/**
	 * Return the current balance of the user
	 * @return - balance
	 */
	public double getBalance()
	{
		return balance;
	}
	
	/**
	 * User purchases shares of a stock
	 * @param id - ID of celebrity to be purchased
	 * @param quantity - number of shares to purchase
	 * @param purchasePrice - price per share to purchase stock at
	 * @return - true if user is successful at buying shares, false otherwise
	 */
	public boolean buyStock( Long id, int quantity, double purchasePrice )
	{
		// Check if the user has enough money to purchase given number of shares
		// Check to make sure quantity to purchase is greater than 0
		if( balance-(quantity*purchasePrice) >= 0 && quantity>0)
		{   
			// Initialize DataStore object to make changes to Google DataStore
			ds = new DataStore();
			// Update the balance of the user
			balance -= ( quantity*purchasePrice );
			// Create a new OwnedStock object using given ID, quantity, and purchase price
			OwnedStock ownedStock = new OwnedStock( id, this.uid,quantity, purchasePrice );
			// Insert OwnedStock into the Google DataStore
			ds.insertOwnedStock(ownedStock);
			// Close the DataStore object
			ds.close();
			// Stock purchasing is successful
			return true;
		}
		else
		{
			// User does not have enough money or quantity is invalid
			// Stock purchasing is not successful
			return false;
		}
	}

	/**
	 * Sell a stock in ownedstock
	 * @param ownedStock - OwnedStock object
	 * @param quantity - number of stocks to sell
	 * @param currentPrice - current price  
	 */
	public boolean sellStock(OwnedStock ownedStock, int quantity , double currentPrice )
	{
		//when the User tries to sell more than he ownes
		if ( quantity > ownedStock.getQuantity()) return false;	
		
		//decrement the quantity of owned stock
		ownedStock.subQuantity( quantity );
		//add the stock value to the balance
		this.balance += currentPrice * (double)quantity;	
		return true;
	}
	
	/**
	 * Return the current asset value of user
	 * @return - asset value
	 */
	public double getAssetValue()
	{
		return assetValue;
	}
	
	/**
	 * Return the previous asset value of user
	 * @return - previous asset value
	 */
	public double getPrevAssetValue()
	{
		return prevAssetValue;
	}
	
	/**
	 * Return the highest asset value of user
	 * @return - maximum asset value
	 */
	public double getMaxAssetValue()
	{
		return maxAssetValue;
	}
	
	/**
	 * User is no longer using application
	 */
	public void removeUser()
	{
		is_app_user = false;
	}
	
	/**
	 * Set user's balance
	 * @param newBalance - new user balance
	 */
	public void setBalance( double newBalance )
	{
		balance = newBalance;
	}
	
	/**
	 * Sets the new asswet value
	 * @param newValue - asset value that is already calculated 
	 */
	public void setAssetValue( double newValue )
	{
		//to keep only 50 previous asset records
		if ( prevAssetValues.size() == 50 )
			prevAssetValues.remove(0);
		
		//set maximum if the new one is the new max
		if ( newValue > maxAssetValue )
			maxAssetValue = newValue;
		
		prevAssetValues.add( newValue);
		//shifting the tmp asset value
		prevAssetValue = tmp1;
		tmp1 = tmp2;
		tmp2 = tmp3;
		tmp3 = tmp4;
		tmp4 = tmp5;
		tmp5 = assetValue;
		assetValue = newValue;
	}

	/**
	 * Compare this user with another user based on asset values
	 * @param user - another user to compare to
	 */
	public int compareTo( User user ) 
	{
		if ( this.assetValue == user.getAssetValue() )
			return 0;
		else if ( this.assetValue < user.getAssetValue() )
			return 1;
		else
			return -1;
	}
	
	/**
	 * Retrieves the prices of stock in a string
	 */
	public String getStringPrices()
	{
		// Iterates through array list to retrieve prices and put into string
		String stringPrices = prevAssetValues.get(0).toString();
		for(int i=1; i<prevAssetValues.size(); i++)
		{
			stringPrices += "," + prevAssetValues.get(i).toString();
		}
		return stringPrices;
	}
	
	/**
	 * Creates string containing address to graph image
	 */ 
	public String getGraph()
	{		
		double gridValue = (100/(this.getMaxAssetValue())) * 10;
		// Creates a string containing address to graph image.
		String graphImage = "http://chart.apis.google.com/chart?"
		+ "chtt=AssetValue+History&"
		+ "cht=lc&chs=500x300&chd=t:"
		+ getStringPrices() + "&"
		+ "chxr=1,0," + this.getMaxAssetValue() + "&chds=0," + this.getMaxAssetValue() + "&"
		+ "chco=4d89f9&"
		+ "chxt=x,y&chxl=0:|&"
		+ "chls=3,1,0&"
		+ "chg=0," + gridValue + ",5,5";
		
		return graphImage;
	}
}

